﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using DomainDriver.CommonUtilities.Enums;

namespace DomainDriver.DomainModeling.StorageManagers.DataSetStorage
{
    public class DataSetSerializationUtilities
    {
        public static void SerializeNullableField<FIELD_TYPE>(Nullable<FIELD_TYPE> field, DataRow dataRow, DataColumn fieldColumn)
            where FIELD_TYPE : struct
        { SerializeNullableField<FIELD_TYPE>(field, dataRow, fieldColumn.ColumnName); }

        public static void SerializeNullableField<FIELD_TYPE>(Nullable<FIELD_TYPE> field, DataRow dataRow, string fieldColumnName)
            where FIELD_TYPE : struct
        {
            if (!field.HasValue)
            {
                dataRow[fieldColumnName] = DBNull.Value;
            }
            else
            {
                dataRow[fieldColumnName] = field.Value;
            }
        }

        public static void SerializeNullableField<ACTUAL_FIELD_TYPE, STORED_FIELD_TYPE>(Nullable<ACTUAL_FIELD_TYPE> field, DataRow dataRow, DataColumn fieldColumn)
            where ACTUAL_FIELD_TYPE : struct
            where STORED_FIELD_TYPE : struct
        { SerializeNullableField<ACTUAL_FIELD_TYPE, STORED_FIELD_TYPE>(field, dataRow, fieldColumn.ColumnName); }

        public static void SerializeNullableField<ACTUAL_FIELD_TYPE, STORED_FIELD_TYPE>(Nullable<ACTUAL_FIELD_TYPE> field, DataRow dataRow, string fieldColumnName)
            where ACTUAL_FIELD_TYPE : struct
            where STORED_FIELD_TYPE : struct
        {
            if (!field.HasValue)
            {
                dataRow[fieldColumnName] = DBNull.Value;
            }
            else
            {
                ACTUAL_FIELD_TYPE actualValue = field.Value;
                STORED_FIELD_TYPE storedValue = (STORED_FIELD_TYPE)Convert.ChangeType(actualValue, typeof(STORED_FIELD_TYPE));
                dataRow[fieldColumnName] = storedValue;
            }
        }

        public static void DeserializeNullableField<FIELD_TYPE>(out Nullable<FIELD_TYPE> field, DataRow dataRow, DataColumn fieldColumn)
            where FIELD_TYPE : struct
        { DeserializeNullableField<FIELD_TYPE>(out field, dataRow, fieldColumn.ColumnName); }

        public static void DeserializeNullableField<FIELD_TYPE>(out Nullable<FIELD_TYPE> field, DataRow dataRow, string fieldColumnName)
            where FIELD_TYPE : struct
        {
            if (dataRow.IsNull(fieldColumnName))
            {
                field = null;
            }
            else
            {
                FIELD_TYPE value = (FIELD_TYPE)dataRow[fieldColumnName];
                field = value;
            }
        }

        public static void DeserializeNullableField<ACTUAL_FIELD_TYPE, STORED_FIELD_TYPE>(out Nullable<ACTUAL_FIELD_TYPE> field, DataRow dataRow, DataColumn fieldColumn)
            where ACTUAL_FIELD_TYPE : struct, IComparable, IFormattable, IConvertible
            where STORED_FIELD_TYPE : struct
        { DeserializeNullableField<ACTUAL_FIELD_TYPE, STORED_FIELD_TYPE>(out field, dataRow, fieldColumn.ColumnName); }

        public static void DeserializeNullableField<ACTUAL_FIELD_TYPE, STORED_FIELD_TYPE>(out Nullable<ACTUAL_FIELD_TYPE> field, DataRow dataRow, string fieldColumnName)
            where ACTUAL_FIELD_TYPE : struct, IComparable, IFormattable, IConvertible
            where STORED_FIELD_TYPE : struct
        {
            if (dataRow.IsNull(fieldColumnName))
            {
                field = null;
            }
            else
            {
                Type actualType = typeof(ACTUAL_FIELD_TYPE);
                ACTUAL_FIELD_TYPE actualValue = default(ACTUAL_FIELD_TYPE);
                STORED_FIELD_TYPE storedValue = (STORED_FIELD_TYPE)dataRow[fieldColumnName];

                if (!actualType.IsEnum)
                {
                    actualValue = (ACTUAL_FIELD_TYPE)Convert.ChangeType(storedValue, actualType);
                }
                else
                {
                    int storedInt = Convert.ToInt32(storedValue);
                    actualValue = EnumUtilities.ConvertIntToEnum<ACTUAL_FIELD_TYPE>(storedInt);
                }
                field = actualValue;
            }
        }
    }
}